package com.youedata.util;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.tobato.fastdfs.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.google.common.collect.Maps;
import com.youedata.base.consts.ConstantsContext;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @desc: FastDFS工具
 * @author: hao.yan
 * @date: 7:25
 */
@Slf4j
@Component
public class FastDFSKit {

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private ThumbImageConfig thumbImageConfig;


    /**
     * 上传指定尺寸的压缩图片
     *
     * @param file   文件对象
     * @param width  压缩宽度
     * @param height 压缩高度
     * @return 文件访问地址
     * @throws IOException IOException
     */
    public Map<String, String> uploadImageThumbnail(MultipartFile file, int width, int height) throws IOException {
        Map<String, String> map = Maps.newHashMap();

        Validate.notNull(file);
        String originalFileName = file.getOriginalFilename();
        String imageThumbnailPath = ConstantsContext.getFileUploadPath() + File.separator + IdWorker.get32UUID() + ".jpg";

        Thumbnails.of(file.getInputStream()).size(width, height).keepAspectRatio(false).toFile(imageThumbnailPath);
        File imageThumbnail = new File(imageThumbnailPath);

        StorePath storePath = storageClient.uploadFile(FileUtil.getInputStream(imageThumbnail), FileUtil.size(imageThumbnail), FilenameUtils.getExtension(file.getOriginalFilename()), null);

        FileUtil.del(imageThumbnail);

        // 原始文件名
        map.put("originalFileName", originalFileName);
        // 原图相对地址
        map.put("imgUrlRelative", storePath.getFullPath());
        // 原图完整访问地址
        map.put("imgUrlFull", getResAccessUrl(storePath));

        return map;
    }

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException IOException
     */
    public Map<String, String> uploadFile(MultipartFile file) throws IOException {
        Map<String, String> map = Maps.newHashMap();

        Validate.notNull(file);
        String originalFileName = file.getOriginalFilename();
        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);

        // 原始文件名
        map.put("originalFileName", originalFileName);
        // 相对地址
        map.put("urlRelative", storePath.getFullPath());
        // 完整访问地址
        map.put("urlFull", getResAccessUrl(storePath));

        return map;
    }

    /**
     * 上传文件并生成缩略图
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException IOException
     */
    public Map<String, String> uploadImageAndCrtThumbImage(MultipartFile file) throws IOException {
        Validate.notNull(file);
        String originalFileName = file.getOriginalFilename();

        Map<String, String> imgMap = Maps.newHashMap();
        StorePath storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);

        // 原始文件名
        imgMap.put("originalFileName", originalFileName);
        // 原图相对地址
        imgMap.put("imgUrlRelative", storePath.getFullPath());
        // 原图完整访问地址
        imgMap.put("imgUrlFull", getResAccessUrl(storePath));
        // 缩略图相对地址
        imgMap.put("imgSmallUrlRelative", storePath.getGroup() + File.separator + thumbImageConfig.getThumbImagePath(storePath.getPath()));
        // 缩略图完整访问地址
        imgMap.put("imgSmallUrlFull", getSmallResAccessUrl(storePath));

        return imgMap;
    }

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException IOException
     */
    public String uploadFile(File file) throws IOException {
        FileInputStream inputStream = new FileInputStream(file);
        StorePath storePath = storageClient.uploadFile(inputStream, file.length(), FilenameUtils.getExtension(file.getName()), null);
        return getResAccessUrl(storePath);
    }

    /**
     * 将一段字符串生成一个文件上传
     *
     * @param content       文件内容
     * @param fileExtension fileExtension
     * @return String
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    /**
     * 封装图片完整URL地址
     */
    private String getResAccessUrl(StorePath storePath) {
        return fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
    }

    /**
     * 封装缩略图完整URL地址
     */
    private String getSmallResAccessUrl(StorePath storePath) {
        return fdfsWebServer.getWebServerUrl() + storePath.getGroup() + thumbImageConfig.getThumbImagePath(storePath.getPath());
    }

    /**
     * 下载文件
     *
     * @param fileUrl 文件url
     * @return byte[]
     */
    public byte[] download(String fileUrl) {
        String group = fileUrl.substring(0, fileUrl.indexOf("/"));
        String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
        return storageClient.downloadFile(group, path, new DownloadByteArray());
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问地址
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.praseFromUrl(fileUrl);
            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 返回前台文件流
     *
     * @author hao.yan
     */
    private static ResponseEntity<InputStreamResource> renderFile(String fileName, InputStream inputStream) {
        InputStreamResource resource = new InputStreamResource(inputStream);
        String dfileName = null;
        try {
            dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", dfileName);
        return new ResponseEntity<>(resource, headers, HttpStatus.CREATED);
    }

    /**
     * 返回前台文件流
     *
     * @author hao.yan
     */
    public static ResponseEntity<InputStreamResource> renderFile(String fileName, String filePath) {
        try {
            final FileInputStream inputStream = new FileInputStream(filePath);
            return renderFile(fileName, inputStream);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("文件读取错误");
        }
    }

    /**
     * 返回前台文件流
     *
     * @author hao.yan
     */
    private static ResponseEntity<InputStreamResource> renderFile(String fileName, byte[] fileBytes) {
        return renderFile(fileName, new ByteArrayInputStream(fileBytes));
    }

    /**
     * UEditor上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException IOException
     */
    public Map<String, String> ueditorUploadFile(MultipartFile file) throws IOException {
        Map<String, String> map = Maps.newHashMap();

        Validate.notNull(file);
        String originalFileName = file.getOriginalFilename();
        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);

        // 原始文件名
        map.put("original", originalFileName);
        // 相对地址
        map.put("state", "SUCCESS");
        // 完整访问地址
        map.put("url", getResAccessUrl(storePath));

        return map;
    }

    public Map<String, String> ueditorUploadFileSize(MultipartFile file,int width ,int height) throws IOException {
        Map<String, String> map = Maps.newHashMap();

        Validate.notNull(file);
        String originalFileName = file.getOriginalFilename();

        String imageThumbnailPath = ConstantsContext.getFileUploadPath() + File.separator + IdWorker.get32UUID() + ".jpg";
        Thumbnails.of(file.getInputStream()).size(width, height).keepAspectRatio(false).toFile(imageThumbnailPath);
        File imageThumbnail = new File(imageThumbnailPath);
        StorePath storePath = storageClient.uploadFile(FileUtil.getInputStream(imageThumbnail), FileUtil.size(imageThumbnail), FilenameUtils.getExtension(file.getOriginalFilename()), null);
        FileUtil.del(imageThumbnail);

        // 原始文件名
        map.put("original", originalFileName);
        // 相对地址
        map.put("state", "SUCCESS");
        // 完整访问地址
        map.put("url", getResAccessUrl(storePath));

        return map;
    }
}
